package org.apache.rocketmq.proxy.config;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Charsets;
import com.google.common.io.CharStreams;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.common.constant.LoggerName;
import org.apache.rocketmq.logging.org.slf4j.Logger;
import org.apache.rocketmq.logging.org.slf4j.LoggerFactory;

import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.concurrent.atomic.AtomicReference;



/**
 * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
 * @author：陈清风扬，个人微信号：chenqingfengyangjj。
 * @date:2024/12/31
 * @方法描述：Proxy模块的配置类
 */
public class Configuration {
    private final static Logger log = LoggerFactory.getLogger(LoggerName.PROXY_LOGGER_NAME);
    private final AtomicReference<ProxyConfig> proxyConfigReference = new AtomicReference<>();
    public static final String CONFIG_PATH_PROPERTY = "com.rocketmq.proxy.configPath";

    //初始化的时候会创建一个ProxyConfig对象，然后将本地配置文件中的数据加载到这个ProxyConfig对象中
    public void init() throws Exception {
        //这里就是加载本地配置文件的操作
        String proxyConfigData = loadJsonConfig();
        //把配置信息转换成ProxyConfig对象
        ProxyConfig proxyConfig = JSON.parseObject(proxyConfigData, ProxyConfig.class);
        proxyConfig.initData();
        //把ProxyConfig对象设置到proxyConfigReference对象中
        setProxyConfig(proxyConfig);
    }


    /**
     * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
     * @author：陈清风扬，个人微信号：chenqingfengyangjj。
     * @date:2024/12/31
     * @方法描述：根据用户定义的Proxy模块的配置文件路径，加载配置文件的方法
     */
    public static String loadJsonConfig() throws Exception {
        //得到配置文件的名称
        String configFileName = ProxyConfig.DEFAULT_CONFIG_FILE_NAME;
        //先从系统属性中得到配置文件的路径
        String filePath = System.getProperty(CONFIG_PATH_PROPERTY);
        if (StringUtils.isBlank(filePath)) {
            //如果系统属性中没有配置文件的路径，那么就从类路径下加载配置文件
            final String testResource = "conf/" + configFileName;
            try (InputStream inputStream = Configuration.class.getClassLoader().getResourceAsStream(testResource)) {
                if (null != inputStream) {
                    return CharStreams.toString(new InputStreamReader(inputStream, Charsets.UTF_8));
                }
            }//如果类路径下没有配置文件，那么就从用户设置在环境变量中的路径中加载配置文件
            filePath = new File(ConfigurationManager.getProxyHome() + File.separator + "conf", configFileName).toString();
        }
        File file = new File(filePath);
        log.info("The current configuration file path is {}", filePath);
        if (!file.exists()) {
            log.warn("the config file {} not exist", filePath);
            throw new RuntimeException(String.format("the config file %s not exist", filePath));
        }
        long fileLength = file.length();
        if (fileLength <= 0) {
            log.warn("the config file {} length is zero", filePath);
            throw new RuntimeException(String.format("the config file %s length is zero", filePath));
        }
        //在这里把配置文件的内容读取出来，以字符串的形式返回
        return new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8);
    }

    public ProxyConfig getProxyConfig() {
        return proxyConfigReference.get();
    }

    public void setProxyConfig(ProxyConfig proxyConfig) {
        proxyConfigReference.set(proxyConfig);
    }
}

